package event

import (
	"fmt"
	"strings"
	"time"

	"go.uber.org/zap"

	"tinyGW/app/api/repository"
	"tinyGW/app/models"
	"tinyGW/pkg/service/event"
)

// Event3761 3761-BY协议事件结构
type Event3761 struct {
	DeviceAddr  string                 // 设备地址
	EventType   string                 // 事件类型
	EventTime   time.Time              // 事件时间
	TableNumber string                 // 表号
	EventData   map[string]interface{} // 事件数据
	RawData     []byte                 // 原始数据
}

// EventHandler3761 3761-BY事件处理函数类型
type EventHandler3761 func(event *Event3761)

var (
	// 事件处理函数映射
	eventHandlers3761 = make(map[string]EventHandler3761)
)

// RegisterEventHandler3761 注册3761-BY事件处理函数
func RegisterEventHandler3761(eventType string, handler EventHandler3761) {
	eventHandlers3761[eventType] = handler
	// zap.S().Infof("注册3761-BY事件处理函数: %s", eventType)
}

// UnregisterEventHandler3761 注销3761-BY事件处理函数
func UnregisterEventHandler3761(eventType string) {
	delete(eventHandlers3761, eventType)
	// zap.S().Infof("注销3761-BY事件处理函数: %s", eventType)
}

// IsF254ActiveReport 检查是否是F254主动上报数据
func IsF254ActiveReport(data []byte) bool {
	if len(data) < 18 {
		return false
	}

	// 检查AFN和DT来判断是否是F254主动上报
	afn := data[12] // AFN在第13字节
	dt1 := data[16] // DT1在第17字节
	dt2 := data[17] // DT2在第18字节
	// AFN=10H(数据转发), DT1=7FH, DT2=04H 对应F254主动上报
	return afn == 0x10 && dt1 == 0x7F && dt2 == 0x04
}

// ParseF254ActiveReport 解析F254主动上报事件（使用rgele.py方案为主，elec.py做验证）
func ParseF254ActiveReport(deviceAddr string, data []byte) (*Event3761, error) {
	event := &Event3761{
		DeviceAddr: deviceAddr,
		EventType:  "f254_report",
		EventTime:  time.Now(),
		EventData:  make(map[string]interface{}),
		RawData:    data,
	}

	// 方案1：使用rgele.py的顺序提取方案（主方案）
	parsedDataRegex, errRegex := parseF254DataRegex(data)

	// 方案2：使用elec.py的原方案（验证方案）
	parsedDataElec, errElec := parseF254Data(data)

	// 优先使用rgele方案
	var primaryData map[string]interface{}
	var primaryErr error

	if errRegex == nil {
		primaryData = parsedDataRegex
		primaryErr = errRegex

		// 如果两个方案都成功，进行数据对比验证
		if errElec == nil {
			compareAndLogDifferences(parsedDataRegex, parsedDataElec, deviceAddr)
		}
	} else if errElec == nil {
		// rgele方案失败，使用elec方案兜底
		zap.S().Warnf("设备[%s] rgele方案解析失败: %v, 使用elec方案兜底", deviceAddr, errRegex)
		primaryData = parsedDataElec
		primaryErr = errElec
	} else {
		// 两个方案都失败，使用最简单的兜底解析
		zap.S().Warnf("设备[%s] 两种方案都解析失败, rgele: %v, elec: %v", deviceAddr, errRegex, errElec)

		if len(data) >= 34 {
			energyValue := uint32(data[30]) +
				(uint32(data[31]) << 8) +
				(uint32(data[32]) << 16) +
				(uint32(data[33]) << 24)
			event.EventData["energy"] = float64(energyValue) / 100.0
		}
		if len(data) >= 36 {
			power := (uint16(data[34]) << 8) | uint16(data[35])
			event.EventData["power"] = float64(power) / 10.0
		}
		if len(data) >= 38 {
			voltage := (uint16(data[36]) << 8) | uint16(data[37])
			event.EventData["voltage"] = float64(voltage) / 10.0
		}
		if len(data) >= 40 {
			current := (uint16(data[38]) << 8) | uint16(data[39])
			event.EventData["current"] = float64(current) / 100.0
		}
		if len(data) >= 42 {
			statusWord := (uint16(data[40]) << 8) | uint16(data[41])
			event.EventData["status_word"] = statusWord
		}
		event.EventData["raw"] = data
		return event, nil
	}

	// 使用主方案的数据
	if primaryErr == nil {
		for key, value := range primaryData {
			event.EventData[key] = value
		}

		// 设置表号（如果解析到了）
		if tableNumber, ok := primaryData["table_number"].(string); ok {
			event.TableNumber = tableNumber
		}

		// 设置事件时间（如果解析到了）
		if eventTime, ok := primaryData["event_time"].(string); ok {
			if t, err := time.Parse("2006-01-02 15:04:05", eventTime); err == nil {
				event.EventTime = t
			}
		}

		// 标记使用的解析方案
		event.EventData["parse_method"] = "rgele"
	}

	return event, nil
}

// parse3761Event 解析3761-BY事件数据
func parse3761Event(deviceAddr string, data []byte) (*Event3761, error) {
	event := &Event3761{
		DeviceAddr: deviceAddr,
		EventData:  make(map[string]interface{}, 8), // 预分配合理容量，减少扩容
		EventTime:  time.Now(),                      // 默认使用当前时间
	}

	// 只在Debug模式下复制原始数?
	if zap.S().Level() == zap.DebugLevel {
		event.RawData = make([]byte, len(data))
		copy(event.RawData, data)
	}

	// 确保数据长度足够
	if len(data) < 18 {
		return nil, fmt.Errorf("数据长度不足")
	}

	// 检查是否是F254主动上报
	if !IsF254ActiveReport(data) {
		return nil, fmt.Errorf("非F254主动上报数据")
	}

	// 提取表地址（通常在用户数据区域）
	if len(data) >= 30 {
		// 表号通常在用户数据区域的特定位置，这里假设在位置20-25
		var tableNumber string
		for i := 20; i < 26 && i < len(data); i++ {
			tableNumber += fmt.Sprintf("%02X", data[i])
		}
		event.TableNumber = tableNumber
	}

	// 设置事件类型
	event.EventType = "f254_report" // F254主动上报

	// 解析用户数据区域
	if len(data) >= 40 {
		// 这里根据3761-BY协议的具体格式解析用户数?
		// 示例：解析电能数�?
		parseEnergyData(data, event)
	}

	return event, nil
}

// parseF254DataRegex 按照rgele.py方案顺序提取TAG数据（主方案）
func parseF254DataRegex(data []byte) (map[string]interface{}, error) {
	result := make(map[string]interface{})

	if len(data) < 30 {
		return result, fmt.Errorf("F254数据长度不足")
	}

	// 跳过帧头和控制信息，定位到F254数据部分（通常从索引18开始）
	dataStart := 18
	if len(data) < dataStart+12 {
		return result, fmt.Errorf("F254数据格式错误")
	}

	// 解析模块维测数据(8字节)
	maintainData := data[dataStart+1 : dataStart+9]
	result["csq"] = int(maintainData[0]) // 信号强度

	// 数据协议类型(1字节)
	protocolType := data[dataStart+9]
	result["protocol_type"] = int(protocolType)

	// 透明转发内容字节数k(2字节)
	contentLen := uint16(data[dataStart+10]) | (uint16(data[dataStart+11]) << 8)

	// 检查透明转发内容
	contentStart := dataStart + 12
	if len(data) < contentStart+int(contentLen) {
		return result, fmt.Errorf("透明转发内容长度不足")
	}

	content := data[contentStart : contentStart+int(contentLen)]
	if len(content) < 8 {
		return result, fmt.Errorf("透明转发内容格式错误")
	}

	// 解析透明转发内容：0xFD + 帧长度(2字节) + 控制字(2字节) + 时间控制字(2字节) + TAG个数(1字节)
	if content[0] != 0xFD {
		return result, fmt.Errorf("透明转发内容标识错误，期望0xFD，实际0x%02X", content[0])
	}

	tagCount := int(content[7])

	// 使用顺序提取TAG的方式（rgele.py方案的核心）
	tagDataStart := 8
	for i := 0; i < tagCount && tagDataStart < len(content)-2; i++ {
		if tagDataStart+2 >= len(content) {
			break
		}

		// 读取TAG（2字节) - 大端序解析
		tag := (uint16(content[tagDataStart]) << 8) | uint16(content[tagDataStart+1])
		tagDataStart += 2

		// 根据TAG值获取数据长度
		dataLen := getTagDataLength(tag)
		if tagDataStart+dataLen > len(content) {
			zap.S().Debugf("TAG 0x%04X 数据长度不足，期望%d字节，剩余%d字节", tag, dataLen, len(content)-tagDataStart)
			break
		}

		tagData := content[tagDataStart : tagDataStart+dataLen]
		tagDataStart += dataLen

		// 解析具体TAG数据
		parseTagData(tag, tagData, result)
	}

	return result, nil
}

// compareAndLogDifferences 对比两种解析方案的差异并记录日志
func compareAndLogDifferences(regexData, elecData map[string]interface{}, deviceAddr string) {
	// 关键字段对比
	keyFields := []string{"energy", "energy_bcd", "table_number", "voltage", "current", "power", "status_word"}

	hasDifference := false
	var differences []string

	for _, field := range keyFields {
		regexVal, regexOk := regexData[field]
		elecVal, elecOk := elecData[field]

		// 都存在才对比
		if regexOk && elecOk {
			// 对于float64类型，使用精度对比
			regexFloat, regexIsFloat := regexVal.(float64)
			elecFloat, elecIsFloat := elecVal.(float64)

			if regexIsFloat && elecIsFloat {
				// 允许0.01的误差
				diff := regexFloat - elecFloat
				if diff < 0 {
					diff = -diff
				}
				if diff > 0.01 {
					hasDifference = true
					differences = append(differences, fmt.Sprintf("%s: rgele=%.2f, elec=%.2f", field, regexFloat, elecFloat))
				}
			} else if regexVal != elecVal {
				hasDifference = true
				differences = append(differences, fmt.Sprintf("%s: rgele=%v, elec=%v", field, regexVal, elecVal))
			}
		} else if regexOk != elecOk {
			// 一个有一个没有
			hasDifference = true
			if regexOk {
				differences = append(differences, fmt.Sprintf("%s: rgele=%v, elec=<不存在>", field, regexVal))
			} else {
				differences = append(differences, fmt.Sprintf("%s: rgele=<不存在>, elec=%v", field, elecVal))
			}
		}
	}

	if hasDifference {
		zap.S().Warnf("设备[%s] 两种解析方案结果不一致，已采用rgele方案。差异: %s", deviceAddr, strings.Join(differences, "; "))
	} else {
		zap.S().Debugf("设备[%s] 两种解析方案结果一致", deviceAddr)
	}
}

// parseF254Data 按照3761-BY协议7.4节正确解析F254主动上报数据（elec.py方案，作为验证）
func parseF254Data(data []byte) (map[string]interface{}, error) {
	result := make(map[string]interface{})

	if len(data) < 30 {
		return result, fmt.Errorf("F254数据长度不足")
	}

	// 跳过帧头和控制信息，定位到F254数据部分（通常从索?8开始）
	dataStart := 18
	if len(data) < dataStart+12 {
		return result, fmt.Errorf("F254数据格式错误")
	}

	// 解析F254数据结构
	// 预留(1字节) + 模块维测数据(8字节) + 数据协议类型(1字节) + 透明转发内容字节数k(2字节)
	reserved := data[dataStart] // 预留
	_ = reserved                // 预留字段暂不使用

	// 模块维测数据(8字节)
	maintainData := data[dataStart+1 : dataStart+9]
	result["csq"] = int(maintainData[0]) // 信号强度

	// 数据协议类型(1字节)
	protocolType := data[dataStart+9]
	result["protocol_type"] = int(protocolType)

	// 透明转发内容字节数k(2字节)
	contentLen := uint16(data[dataStart+10]) | (uint16(data[dataStart+11]) << 8)

	// 检查透明转发内容
	contentStart := dataStart + 12
	if len(data) < contentStart+int(contentLen) {
		return result, fmt.Errorf("透明转发内容长度不足")
	}

	content := data[contentStart : contentStart+int(contentLen)]
	if len(content) < 8 {
		return result, fmt.Errorf("透明转发内容格式错误")
	}

	// 解析透明转发内容?xFD + 帧长?2字节) + 控制?2字节) + 时间控制?2字节) + TAG个数(1字节)
	if content[0] != 0xFD {
		return result, fmt.Errorf("透明转发内容标识错误，期�?xFD，实�?x%02X", content[0])
	}

	tagCount := int(content[7])

	// 解析TAG数据
	tagDataStart := 8
	for i := 0; i < tagCount && tagDataStart < len(content)-2; i++ {
		if tagDataStart+2 >= len(content) {
			break
		}

		// 读取TAG?2字节) - 修改为大端序解析
		tag := (uint16(content[tagDataStart]) << 8) | uint16(content[tagDataStart+1])
		tagDataStart += 2

		// 根据TAG值解析对应的数据
		dataLen := getTagDataLength(tag)
		if tagDataStart+dataLen > len(content) {
			zap.S().Warnf("TAG 0x%04X 数据长度不足，期?d字节", tag, dataLen)
			break
		}

		tagData := content[tagDataStart : tagDataStart+dataLen]
		tagDataStart += dataLen

		// 解析具体TAG数据
		parseTagData(tag, tagData, result)
	}

	return result, nil
}

// getTagDataLength 根据TAG值获取数据长度（扩展rgele.py的TAG定义）
func getTagDataLength(tag uint16) int {
	switch tag {
	case 0x0001: // 表号
		return 6
	case 0x0002: // 时间
		return 7
	case 0x0003: // 整点冻结时间
		return 5
	case 0x0004, 0x0005: // 整点冻结正向/反向有功总电能
		return 4
	case 0x0006: // 上1次日冻结时间
		return 5
	case 0x0007: // 上1次日冻结正向有功电能数据
		return 20
	case 0x0008: // 上1次日冻结反向有功电能数据
		return 20
	case 0x0014: // 电表运行状态字3
		return 2
	case 0x0015, 0x0016, 0x0017: // A/B/C相电压
		return 2
	case 0x0018, 0x0019, 0x001A: // A/B/C相电流
		return 3
	case 0x001B, 0x001C, 0x001D, 0x001E: // 有功功率
		return 3
	case 0x001F, 0x0020, 0x0021, 0x0022: // 视在功率
		return 3
	case 0x0023, 0x0024, 0x0025, 0x0026: // 功率因数
		return 2
	case 0x0027, 0x0028, 0x0029, 0x002A, 0x002B: // （当前）组合有功电能
		return 4
	case 0x002C, 0x002D, 0x002E, 0x002F, 0x0030: // （当前）正向有功电能
		return 4
	case 0x0049, 0x004A, 0x004B, 0x004C, 0x004D: // （当前）组合无功1电能
		return 4
	case 0x004E, 0x004F, 0x0050, 0x0051, 0x0052: // （当前）组合无功2电能
		return 4
	case 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096: // 状态字1-7
		return 2
	default:
		// 对于未知TAG，尝试从协议文档推断，默认4字节
		zap.S().Debugf("未知TAG 0x%04X，使用默认长度4字节", tag)
		return 4
	}
}

// parseTagData 解析具体TAG数据（扩展支持rgele.py的TAG类型）
func parseTagData(tag uint16, data []byte, result map[string]interface{}) {
	switch tag {
	case 0x0001: // 表号
		if len(data) >= 6 {
			var tableNumber string
			for i := 0; i < 6; i++ {
				tableNumber += fmt.Sprintf("%02X", data[i])
			}
			result["table_number"] = tableNumber
		}

	case 0x0006: // 上1次日冻结时间
		if len(data) >= 5 {
			freezeTime := fmt.Sprintf("%02X%02X%02X%02X%02X", data[0], data[1], data[2], data[3], data[4])
			result["freeze_time"] = freezeTime
		}

	case 0x0002: // 时间 - 7字节BCD格式：YY MM DD WW HH MM SS
		if len(data) >= 7 {
			year := int(data[0])
			month := int(data[1])
			day := int(data[2])
			week := int(data[3])
			hour := int(data[4])
			minute := int(data[5])
			second := int(data[6])

			// 转换为时间字符串
			timeStr := fmt.Sprintf("20%02d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second)
			result["event_time"] = timeStr
			result["week"] = week
			// zap.S().Debugf("TAG 0x%04X (时间): %s, 星期%d", tag, timeStr, week)
		}

	case 0x0004: // 整点冻结正向有功总电:
		if len(data) >= 4 {
			// BCD格式解析电能值，单位kWh，精?.01
			energy := parseBCDEnergy(data)
			result["energy"] = energy
			// zap.S().Debugf("TAG 0x%04X (正向有功总电: %.2f kWh", tag, energy)
		}

	case 0x0005: // 整点冻结反向有功总电:
		if len(data) >= 4 {
			energy := parseBCDEnergy(data)
			result["reverse_energy"] = energy
			// zap.S().Debugf("TAG 0x%04X (反向有功总电: %.2f kWh", tag, energy)
		}

	case 0x002C, 0x0027: // 当前正向有功总电\组合有功电能
		if len(data) >= 4 {
			energy := parseBCDEnergy(data)
			result["energy"] = energy
			result["energy_bcd"] = energy // 添加BCD解析标识，供设备属性更新使?
			// zap.S().Debugf("TAG 0x%04X (当前正向有功总电: %.2f kWh", tag, energy)
		}

	case 0x002D, 0x002E, 0x002F, 0x0030: // 正向有功费率1-4电能
		if len(data) >= 4 {
			energy := parseBCDEnergy(data)
			rateNum := tag - 0x002C // 0x002D对应费率1?x002E对应费率2，依此类?
			result[fmt.Sprintf("energy_rate_%d", rateNum)] = energy
			// zap.S().Debugf("TAG 0x%04X (正向有功费率%d电能): %.2f kWh", tag, rateNum, energy)
		}

	case 0x0014: // 电表运行状态字
		if len(data) >= 2 {
			statusWord := uint16(data[0]) | (uint16(data[1]) << 8)
			result["status_word"] = statusWord
			// zap.S().Debugf("TAG 0x%04X (状态字): 0x%04X", tag, statusWord)
		}

	case 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096: // 状态字1-7
		if len(data) >= 2 {
			statusWord := uint16(data[0]) | (uint16(data[1]) << 8)
			statusNum := tag - 0x0090 // 0x0091对应状态字1，0x0096对应状态字7
			result[fmt.Sprintf("status_word_%d", statusNum)] = statusWord
			// zap.S().Debugf("TAG 0x%04X (状态字%d): 0x%04X", tag, statusNum, statusWord)
		}

	case 0x0015: // A相电:
		if len(data) >= 2 {
			voltage := parseBCDVoltage(data)
			result["voltage_a"] = voltage
			result["voltage"] = voltage // 兼容
			// zap.S().Debugf("TAG 0x%04X (A相电: %.1f V", tag, voltage)
		}

	case 0x0016: // B相电:
		if len(data) >= 2 {
			voltage := parseBCDVoltage(data)
			result["voltage_b"] = voltage
			// zap.S().Debugf("TAG 0x%04X (B相电: %.1f V", tag, voltage)
		}

	case 0x0017: // C相电:
		if len(data) >= 2 {
			voltage := parseBCDVoltage(data)
			result["voltage_c"] = voltage
			// zap.S().Debugf("TAG 0x%04X (C相电: %.1f V", tag, voltage)
		}

	case 0x0018: // A相电:
		if len(data) >= 3 {
			current := parseBCDCurrent(data)
			result["current_a"] = current
			result["current"] = current // 兼容
			// zap.S().Debugf("TAG 0x%04X (A相电: %.3f A", tag, current)
		}

	case 0x0019: // B相电:
		if len(data) >= 3 {
			current := parseBCDCurrent(data)
			result["current_b"] = current
			// zap.S().Debugf("TAG 0x%04X (B相电: %.3f A", tag, current)
		}

	case 0x001A: // C相电:
		if len(data) >= 3 {
			current := parseBCDCurrent(data)
			result["current_c"] = current
			// zap.S().Debugf("TAG 0x%04X (C相电: %.3f A", tag, current)
		}

	case 0x001B: // 瞬时总有功功:
		if len(data) >= 3 {
			power := parseBCDPower(data)
			result["power"] = power
			// zap.S().Debugf("TAG 0x%04X (总有功功: %.4f kW", tag, power)
		}

	case 0x001C: // 瞬时A相有功功:
		if len(data) >= 3 {
			power := parseBCDPower(data)
			result["power_a"] = power
			// zap.S().Debugf("TAG 0x%04X (A相有功功: %.4f kW", tag, power)
		}

	case 0x001D: // 瞬时B相有功功:
		if len(data) >= 3 {
			power := parseBCDPower(data)
			result["power_b"] = power
			// zap.S().Debugf("TAG 0x%04X (B相有功功: %.4f kW", tag, power)
		}

	case 0x001E: // 瞬时C相有功功率
		if len(data) >= 3 {
			power := parseBCDPower(data)
			result["power_c"] = power
			// zap.S().Debugf("TAG 0x%04X (C相有功功率): %.4f kW", tag, power)
		}

	case 0x0049, 0x004A, 0x004B, 0x004C, 0x004D: // 组合无功1电能
		if len(data) >= 4 {
			energy := parseBCDEnergy(data)
			tagName := ""
			switch tag {
			case 0x0049:
				tagName = "reactive_energy_1_total"
				result[tagName] = energy
			case 0x004A:
				tagName = "reactive_energy_1_rate_1"
				result[tagName] = energy
			case 0x004B:
				tagName = "reactive_energy_1_rate_2"
				result[tagName] = energy
			case 0x004C:
				tagName = "reactive_energy_1_rate_3"
				result[tagName] = energy
			case 0x004D:
				tagName = "reactive_energy_1_rate_4"
				result[tagName] = energy
			}
			// zap.S().Debugf("TAG 0x%04X (%s): %.2f kWh", tag, tagName, energy)
		}

	case 0x004E, 0x004F, 0x0050, 0x0051, 0x0052: // 组合无功2电能
		if len(data) >= 4 {
			energy := parseBCDEnergy(data)
			tagName := ""
			switch tag {
			case 0x004E:
				tagName = "reactive_energy_2_total"
				result[tagName] = energy
			case 0x004F:
				tagName = "reactive_energy_2_rate_1"
				result[tagName] = energy
			case 0x0050:
				tagName = "reactive_energy_2_rate_2"
				result[tagName] = energy
			case 0x0051:
				tagName = "reactive_energy_2_rate_3"
				result[tagName] = energy
			case 0x0052:
				tagName = "reactive_energy_2_rate_4"
				result[tagName] = energy
			}
			// zap.S().Debugf("TAG 0x%04X (%s): %.2f kWh", tag, tagName, energy)
		}

	default:
		// 对于未知TAG，记录原始数据
		var hexStr string
		for i, b := range data {
			if i > 0 {
				hexStr += " "
			}
			hexStr += fmt.Sprintf("%02X", b)
		}
		result[fmt.Sprintf("tag_0x%04X", tag)] = hexStr
		// zap.S().Debugf("未知TAG 0x%04X，原始数据: %s", tag, hexStr)
	}
}

// parseBCDEnergy 解析BCD格式的电能值（4字节，精?.01kWh:
func parseBCDEnergy(data []byte) float64 {
	if len(data) < 4 {
		return 0
	}

	// BCD格式?字节，从左到右，精度0.01kWh
	// 例如：[00 00 07 39] 表示 0000.0739 * 100 = 7.39 kWh

	var value uint32 = 0

	// 从左到右处理每个字节的BCD?:
	for i := 0; i < 4; i++ {
		byteVal := data[i]
		lowDigit := byteVal & 0x0F
		highDigit := (byteVal >> 4) & 0x0F

		// 检查BCD有效?:
		if lowDigit > 9 || highDigit > 9 {
			// 如果不是有效BCD，尝试直接按二进制解?:
			rawValue := uint32(data[0]) | (uint32(data[1]) << 8) | (uint32(data[2]) << 16) | (uint32(data[3]) << 24)
			return float64(rawValue) / 100.0
		}

		// 将BCD转换为数值，高位在前
		value = value*100 + uint32(highDigit*10+lowDigit)
	}

	// 精度?.01kWh，所以除?:00
	return float64(value) / 100.0
}

// parseBCDVoltage 解析BCD格式的电压值（2字节，精度0.1V）
// 参考rgele.py的解析算法
func parseBCDVoltage(data []byte) float64 {
	if len(data) < 2 {
		return 0
	}

	// 将BCD转换为字符串
	var bcdStr string
	for i := 0; i < 2; i++ {
		byteVal := data[i]
		highDigit := (byteVal >> 4) & 0x0F
		lowDigit := byteVal & 0x0F

		// 检查BCD有效性
		if lowDigit > 9 || highDigit > 9 {
			// 如果不是有效BCD，尝试直接解析
			rawValue := uint16(data[0]) | (uint16(data[1]) << 8)
			return float64(rawValue) / 10.0
		}

		bcdStr += fmt.Sprintf("%d%d", highDigit, lowDigit)
	}

	// 转换为整数再除以精度
	var value int
	fmt.Sscanf(bcdStr, "%d", &value)
	return float64(value) / 10.0
}

// parseBCDCurrent 解析BCD格式的电流值（3字节，精度0.01A）
// 参考rgele.py的解析算法
func parseBCDCurrent(data []byte) float64 {
	if len(data) < 3 {
		return 0
	}

	// 将BCD转换为字符串
	var bcdStr string
	for i := 0; i < 3; i++ {
		byteVal := data[i]
		highDigit := (byteVal >> 4) & 0x0F
		lowDigit := byteVal & 0x0F

		// 检查BCD有效性
		if lowDigit > 9 || highDigit > 9 {
			// 如果不是有效BCD，尝试直接解析
			rawValue := uint32(data[0]) | (uint32(data[1]) << 8) | (uint32(data[2]) << 16)
			return float64(rawValue) / 100.0
		}

		bcdStr += fmt.Sprintf("%d%d", highDigit, lowDigit)
	}

	// 转换为整数再除以精度（实际精度是0.01A）
	var value int
	fmt.Sscanf(bcdStr, "%d", &value)
	return float64(value) / 100.0
}

// parseBCDPower 解析BCD格式的功率值（3字节，精度0.01kW）
// 参考rgele.py的解析算法
func parseBCDPower(data []byte) float64 {
	if len(data) < 3 {
		return 0
	}

	// 将BCD转换为字符串
	var bcdStr string
	for i := 0; i < 3; i++ {
		byteVal := data[i]
		highDigit := (byteVal >> 4) & 0x0F
		lowDigit := byteVal & 0x0F

		// 检查BCD有效性
		if lowDigit > 9 || highDigit > 9 {
			// 如果不是有效BCD，尝试直接解析
			rawValue := uint32(data[0]) | (uint32(data[1]) << 8) | (uint32(data[2]) << 16)
			return float64(rawValue) / 100.0
		}

		bcdStr += fmt.Sprintf("%d%d", highDigit, lowDigit)
	}

	// 转换为整数再除以精度（实际精度是0.01kW）
	var value int
	fmt.Sscanf(bcdStr, "%d", &value)
	return float64(value) / 100.0
}

// parseEnergyData 解析电能数据（使用rgele方案为主，elec方案验证）
func parseEnergyData(data []byte, event *Event3761) {
	if len(data) < 40 {
		// zap.S().Warnln("电能数据长度不足")
		return
	}

	// 优先使用rgele方案的顺序提取TAG解析方式
	var parsedData map[string]interface{}
	var err error

	parsedDataRegex, errRegex := parseF254DataRegex(data)
	parsedDataElec, errElec := parseF254Data(data)

	if errRegex == nil {
		// rgele方案成功
		parsedData = parsedDataRegex
		err = errRegex

		// 如果elec方案也成功，进行对比
		if errElec == nil {
			compareAndLogDifferences(parsedDataRegex, parsedDataElec, event.DeviceAddr)
		}
	} else if errElec == nil {
		// rgele方案失败，使用elec方案兜底
		zap.S().Warnf("设备[%s] rgele方案解析失败: %v, 使用elec方案", event.DeviceAddr, errRegex)
		parsedData = parsedDataElec
		err = errElec
	} else {
		// 两个方案都失败，使用最简单的兜底解析
		zap.S().Warnf("设备[%s] 两种解析方案都失败", event.DeviceAddr)
	}

	if err == nil && parsedData != nil {
		// zap.S().Debugln("使用TAG解析方式成功")

		// 将TAG解析的结果合并到EventData
		for key, value := range parsedData {
			event.EventData[key] = value
		}

		// 保持兼容性：将新解析的值映射到旧的字段
		if energy, ok := parsedData["energy"].(float64); ok {
			event.EventData["energy"] = energy
			// zap.S().Infof("使用TAG解析电能: %.2f kWh", energy)
		}

		if power, ok := parsedData["power"].(float64); ok {
			event.EventData["power"] = power
		}

		if voltage, ok := parsedData["voltage"].(float64); ok {
			event.EventData["voltage"] = voltage
		} else if voltageA, ok := parsedData["voltage_a"].(float64); ok {
			event.EventData["voltage"] = voltageA // 使用A相电压作为默认电?:
		}

		if current, ok := parsedData["current"].(float64); ok {
			event.EventData["current"] = current
		} else if currentA, ok := parsedData["current_a"].(float64); ok {
			event.EventData["current"] = currentA // 使用A相电流作为默认电?:
		}

		if statusWord, ok := parsedData["status_word"].(uint16); ok {
			event.EventData["status_word"] = statusWord

			// 解析状态位
			event.EventData["cover_open"] = (statusWord & 0x0200) != 0   // 开表盖
			event.EventData["switch_event"] = (statusWord & 0x0010) != 0 // 开合闸事件
		}

		// 如果TAG解析成功，直接返?:
		return
	}

	// zap.S().Warnln("TAG解析失败，使用兜底解析方式")

	// 兜底：使用原始的固定位置解析（保持向后兼容）
	// 原始位置30的解析（保持兼容?:
	if len(data) >= 34 {
		// 标准BCD解码，与Lua插件保持一�?
		bcdValue := float64(0)
		factor := 0.01 // 从小数点?:位开?:
		validBcd := true

		for i := 0; i < 4; i++ {
			byteVal := data[30+i]
			lowDigit := byteVal & 0x0F
			highDigit := (byteVal >> 4) & 0x0F

			if lowDigit > 9 || highDigit > 9 {
				validBcd = false
				break
			}

			bcdValue += float64(lowDigit) * factor
			factor *= 10
			bcdValue += float64(highDigit) * factor
			factor *= 10
		}

		// 原始解析方式（保留以兼容旧代码）
		energyValue := uint32(data[30]) +
			(uint32(data[31]) << 8) +
			(uint32(data[32]) << 16) +
			(uint32(data[33]) << 24)

		// 记录解析结果
		if validBcd {
			event.EventData["energy_bcd"] = bcdValue // BCD解析结果
			// zap.S().Infof("电能BCD解析结果: %.2f kWh", bcdValue)

			// 直接将BCD解析结果设为主要结果
			event.EventData["energy"] = bcdValue
		} else {
			// 兜底使用原始解析方式
			event.EventData["energy"] = float64(energyValue) / 100.0 // 单位kWh
		}
	}

	// 解析功率（示例位?:4-35?:
	if len(data) >= 36 {
		power := (uint16(data[34]) << 8) | uint16(data[35])
		event.EventData["power"] = float64(power) / 10.0 // 单位kW
	}

	// 解析电压（示例位?:6-37?:
	if len(data) >= 38 {
		voltage := (uint16(data[36]) << 8) | uint16(data[37])
		event.EventData["voltage"] = float64(voltage) / 10.0 // 单位V
	}

	// 解析电流（示例位?:8-39?:
	if len(data) >= 40 {
		current := (uint16(data[38]) << 8) | uint16(data[39])
		event.EventData["current"] = float64(current) / 100.0 // 单位A
	}

	// 解析状态字（示例位?:0-41?:
	if len(data) >= 42 {
		statusWord := (uint16(data[40]) << 8) | uint16(data[41])
		event.EventData["status_word"] = statusWord

		// 解析状态位
		event.EventData["cover_open"] = (statusWord & 0x0200) != 0   // 开表盖
		event.EventData["switch_event"] = (statusWord & 0x0010) != 0 // 开合闸事件
	}
}

// handle3761Event 处理解析后的3761-BY事件
func handle3761Event(event *Event3761) {
	if event == nil {
		// zap.S().Warnln("传入?:761-BY事件为空")
		return
	}

	// 查找并调用对应的事件处理函数
	handler, exists := eventHandlers3761[event.EventType]
	if exists {
		// zap.S().Infof("执行3761-BY事件处理函数: %s, 设备: %s", event.EventType, event.DeviceAddr)
		handler(event)
	} else {
		// zap.S().Warnf("未找?:761-BY事件处理函数: %s, 设备: %s", event.EventType, event.DeviceAddr)

		// 针对未注册处理函数的事件类型，调用通用处理逻辑
		handleGeneric3761Event(event)
	}
}

// handleGeneric3761Event 处理通用3761-BY事件
func handleGeneric3761Event(event *Event3761) {
	// 打印事件基本信息
	// zap.S().Infof("通用处理3761-BY事件: 类型=%s, 设备=%s, 时间=%s",
	// 	event.EventType, event.DeviceAddr, event.EventTime.Format("2006-01-02 15:04:05"))

	// 打印所有事件数?:
	// for key, value := range event.EventData {
	// 	zap.S().Infof("事件数据: %s = %v", key, value)
	// }

	// 这里可以添加通用事件处理逻辑，如?:
	// 1. 保存数据到数据库
	// 2. 转发到其他系�?
	// 3. 触发告警?:
}

// ConvertToDeviceAndPublish3761 将事件转换为设备对象并触发DeviceCollectFinish事件
func ConvertToDeviceAndPublish3761(event *Event3761, deviceRepository repository.DeviceRepository, eventBus *event.EventService) {
	if event == nil {
		// zap.S().Warnln("传入?:761-BY事件为空，无法转换为设备对象")
		return
	}

	// 查找设备 - 使用表号查找
	device, err := deviceRepository.FindByCollectorAddr(event.DeviceAddr)
	if err != nil || len(device.Name) == 0 {
		device, err = deviceRepository.FindByAddr(event.TableNumber)
		if err != nil || len(device.Name) == 0 {
			// zap.S().Errorf("查找设备[%s]失败: %v", event.DeviceAddr, err)
			return
		}
		// zap.S().Infof("使用采集器地址[%s]查找设备[%s]成功", event.DeviceAddr, event.TableNumber)
	}

	// 更新设备状?:
	device.Online = true
	device.CollectTime = time.Now().Unix()
	device.CollectTotal += 1
	device.CollectSuccess += 1

	// 调试：打印事件数据内?:

	// 更新设备属?:- 根据报文内容动态设置Reported状?:
	hasEnergyData := false // 标记是否包含电能数据

	for i, property := range device.Type.Properties {
		// 先重置所有属性的Reported状?:
		device.Type.Properties[i].Reported = false

		switch property.Name {
		case "dev_consumption": // 总电?:
			// 直接使用BCD解析结果作为首?:
			if v, ok := event.EventData["energy_bcd"].(float64); ok && v > 0 {
				//zap.S().Infof("使用BCD解析电能 %.2f kWh", v)
				device.Type.Properties[i].Value = v
				device.Type.Properties[i].Reported = true // 标记为可上报
				hasEnergyData = true
			} else if v, ok := event.EventData["energy"].(float64); ok && v > 0 {
				// 兜底使用其他解析结果
				//zap.S().Infof("使用原始解析电能 %.2f kWh", v)
				device.Type.Properties[i].Value = v
				device.Type.Properties[i].Reported = true // 标记为可上报
				hasEnergyData = true
			}
			// 如果没有电能数据，不设置Reported=true，这样就不会上报

		case "dev_remain_amt": // 剩余金额
			if v, ok := event.EventData["remain_amt"].(float64); ok {
				device.Type.Properties[i].Value = v
				device.Type.Properties[i].Reported = true
			}
		case "dev_remain_elec": // 剩余电量
			if v, ok := event.EventData["remain_elec"].(float64); ok {
				device.Type.Properties[i].Value = v
				device.Type.Properties[i].Reported = true
			}
		case "dev_owe_amt": // 欠费金额
			if v, ok := event.EventData["owe_amt"].(float64); ok {
				device.Type.Properties[i].Value = v
				device.Type.Properties[i].Reported = true
			}
		case "dev_owe_elec": // 欠费电量
			if v, ok := event.EventData["owe_elec"].(float64); ok {
				device.Type.Properties[i].Value = v
				device.Type.Properties[i].Reported = true
			}
		case "dev_instant_flow": // 瞬时流量
			if v, ok := event.EventData["instant_flow"].(float64); ok {
				device.Type.Properties[i].Value = v
				device.Type.Properties[i].Reported = true
			}
		case "dev_flow": // 总流量
			if v, ok := event.EventData["flow"].(float64); ok {
				device.Type.Properties[i].Value = v
				device.Type.Properties[i].Reported = true
			}
		case "dev_temp": // 温度值
			if v, ok := event.EventData["temp"].(float64); ok {
				device.Type.Properties[i].Value = v
				device.Type.Properties[i].Reported = true
			}
		case "dev_rh": // 湿度值
			if v, ok := event.EventData["rh"].(float64); ok {
				device.Type.Properties[i].Value = v
				device.Type.Properties[i].Reported = true
			}
		case "dev_pm25": // PM2.5
			if v, ok := event.EventData["pm25"].(float64); ok {
				device.Type.Properties[i].Value = v
				device.Type.Properties[i].Reported = true
			}
		case "dev_co2": // CO2
			if v, ok := event.EventData["co2"].(float64); ok {
				device.Type.Properties[i].Value = v
				device.Type.Properties[i].Reported = true
			}
		case "dev_ch2o": // CH2O
			if v, ok := event.EventData["ch2o"].(float64); ok {
				device.Type.Properties[i].Value = v
				device.Type.Properties[i].Reported = true
			}
		case "dev_voc": // VOC
			if v, ok := event.EventData["voc"].(float64); ok {
				device.Type.Properties[i].Value = v
				device.Type.Properties[i].Reported = true
			}
		case "dev_o2": // O2
			if v, ok := event.EventData["o2"].(float64); ok {
				device.Type.Properties[i].Value = v
				device.Type.Properties[i].Reported = true
			}
		case "dev_co": // CO
			if v, ok := event.EventData["co"].(float64); ok {
				device.Type.Properties[i].Value = v
				device.Type.Properties[i].Reported = true
			}
		case "dev_updown": // 上下行
			if v, ok := event.EventData["updown"].(float64); ok {
				device.Type.Properties[i].Value = v
				device.Type.Properties[i].Reported = true
			} else if v, ok := event.EventData["updown"].(int); ok {
				device.Type.Properties[i].Value = float64(v)
				device.Type.Properties[i].Reported = true
			}
		case "dev_status": // 运行状态
			if v, ok := event.EventData["status_word"].(uint16); ok {
				device.Type.Properties[i].Value = float64(v)
				device.Type.Properties[i].Reported = true
			} else if v, ok := event.EventData["status_word"].(float64); ok {
				device.Type.Properties[i].Value = v
				device.Type.Properties[i].Reported = true
			} else {
				// 检查状态字1-7
				for j := 1; j <= 7; j++ {
					statusKey := fmt.Sprintf("status_word_%d", j)
					if v, ok := event.EventData[statusKey].(uint16); ok {
						device.Type.Properties[i].Value = float64(v)
						device.Type.Properties[i].Reported = true
						// zap.S().Debugf("使用状态字%d值: 0x%04X", j, v)
						break
					}
				}
			}
		case "dev_fix": // 检修状态
			if v, ok := event.EventData["fix"].(float64); ok {
				device.Type.Properties[i].Value = v
				device.Type.Properties[i].Reported = true
			} else if v, ok := event.EventData["fix"].(int); ok {
				device.Type.Properties[i].Value = float64(v)
				device.Type.Properties[i].Reported = true
			}
		case "dev_err": // 故障状态
			if v, ok := event.EventData["err"].(float64); ok {
				device.Type.Properties[i].Value = v
				device.Type.Properties[i].Reported = true
			} else if v, ok := event.EventData["err"].(int); ok {
				device.Type.Properties[i].Value = float64(v)
				device.Type.Properties[i].Reported = true
			}
		case "dev_stp": // 停泊状态
			if v, ok := event.EventData["stp"].(float64); ok {
				device.Type.Properties[i].Value = v
				device.Type.Properties[i].Reported = true
			} else if v, ok := event.EventData["stp"].(int); ok {
				device.Type.Properties[i].Value = float64(v)
				device.Type.Properties[i].Reported = true
			}
		// 保持原有属性映射
		case "dev_power":
			if v, ok := event.EventData["power"].(float64); ok {
				device.Type.Properties[i].Value = v
				device.Type.Properties[i].Reported = true
			}
		case "dev_voltage":
			if v, ok := event.EventData["voltage"].(float64); ok {
				device.Type.Properties[i].Value = v
				device.Type.Properties[i].Reported = true
			}
		case "dev_current":
			if v, ok := event.EventData["current"].(float64); ok {
				device.Type.Properties[i].Value = v
				device.Type.Properties[i].Reported = true
			}
		}
	}

	// 记录报文类型
	if hasEnergyData {
		zap.S().Infof("包含电能数据的报文，将上报dev_consumption字段")
	} else {
		zap.S().Infof("短报文，无电能数据，不上报dev_consumption字段")
	}

	// 调试：打印更新后的设备属性
	// zap.S().Debugf("设备属性赋值后: %+v", device.Type.Properties)

	// 插入属性 original_data
	device.Type.Properties = append(device.Type.Properties, models.DeviceProperty{
		Name:     "original_data",
		Value:    fmt.Sprintf("% 2X", event.RawData),
		Reported: true,
	})

	// 添加解析方法标识
	if parseMethod, ok := event.EventData["parse_method"].(string); ok {
		device.Type.Properties = append(device.Type.Properties, models.DeviceProperty{
			Name:     "parse_method",
			Value:    parseMethod,
			Reported: false, // 不上报到云端，仅用于内部调试
		})
	}

	// 处理告警状?:
	alarmReasons := []string{}

	// 根据状态字判断告警
	if statusWord, ok := event.EventData["status_word"].(uint16); ok {
		if (statusWord & 0x0200) != 0 {
			alarmReasons = append(alarmReasons, "开表盖")
		}
		if (statusWord & 0x0010) != 0 {
			alarmReasons = append(alarmReasons, "开合闸事件")
		}
	}

	// 检查过载
	if _, ok := event.EventData["phase_a_overload"]; ok {
		alarmReasons = append(alarmReasons, "A相过载")
	}

	if len(alarmReasons) > 0 {
		device.AlarmStatus = true
		device.AlarmReason = strings.Join(alarmReasons, ",")
		device.AlarmTime = time.Now().Unix()
		device.AlarmTotal += 1
	} else {
		device.AlarmStatus = false
		device.AlarmReason = ""
	}

	// 保存设备状?:
	err = deviceRepository.Save(&device)
	if err != nil {
		zap.S().Errorf("保存设备[%s]状态失?: %v", device.Name, err)
		return
	}

	// 触发设备采集完成事件
	var e struct {
		Name string
		Data interface{}
	}
	e.Name = "DeviceCollectFinish"
	e.Data = device
	// zap.S().Infof("触发设备[%s]采集完成事件", e.Name)
	zap.S().Debugf("设备[%s]上报原文: [% 2x]", device.Name, event.RawData)
	eventBus.Publish(e)
}
